package com.zhiqiang.nativeplayer.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.zhiqiang.nativeplayer.bean.FileResource;
import com.zhiqiang.nativeplayer.bean.ResourceType;
import com.zhiqiang.nativeplayer.bean.ResourceDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * author：paul
 * date：Created in 22:00 2022/11/21
 * load file list from disk
 */
@Component
@Slf4j
public class FileLoadHandler {
    //video resource path
    //new String[]{"E:/a","E:/toDisk"}
    private static List<String> mainDirPath ;

    private static ArrayList<String> videoSuffixArray;
    private static ArrayList<String> pdfSuffixArray;

    private static List<ResourceDto> videoDtoList = new ArrayList<>();
    private static List<ResourceDto> pdfDtoList = new ArrayList<>();



    /**@return video resource list
     * */
    public List<ResourceDto> getVideoList(){
        return videoDtoList;
    }

    /**@return pdf resource list
     * */
    public List<ResourceDto> getPdfList(){
        return pdfDtoList;
    }



    /**get a dto by serialId from list*/
    public static ResourceDto getBySerialId(String serialId){

        for(ResourceDto item: videoDtoList){
            if(serialId.equals(item.getSerialId())){
            return item;
            }
        }

        for (ResourceDto item: pdfDtoList){
            if(serialId.equals(item.getSerialId())){
                return item;
            }
        }

        return null;
    }

    static{
        //video suffix
        videoSuffixArray = new ArrayList<>();
        videoSuffixArray.add("mp4");
        videoSuffixArray.add("flv");
        videoSuffixArray.add("avi");
        //videoSuffixArray.add("rmvb");
        //videoSuffixArray.add("mkv");
        //pdf suffix
        pdfSuffixArray = new ArrayList<>();
        pdfSuffixArray.add("pdf");

        //init file list
        loadXmlFile();
        log.info("total video:"+videoDtoList.size()+",pdf:"+pdfDtoList.size()+";");
    }

    /** load resource file list from disk
     * @return maybe null
     * */
    private static void loadXmlFile(){

        //file list
        List<File> fileList = new ArrayList<>();

        //load config file
        mainDirPath = getVideoListFromFileResourcePojo();

        //traversal dir array
        log.info("loading directory.");
        for (String i:mainDirPath){
            File mainDirFile = new File(i);
            log.info("dir:"+i);

            //main dir check
            if((!mainDirFile.exists()) || (!mainDirFile.isDirectory())){
                return;
            }

            //get all files
            getAllFilesFromDirectory(mainDirFile, fileList);
        }

        //load dto list from files
        FileListToDto(fileList);
        //

    }

    /**get video list from FileResource pojo */
    private static List<String> getVideoListFromFileResourcePojo(){
        FileResource f =  loadFileResource();
        return f.getFileResourceVideos();
    }


    /**
     * load resource directory path
     * */
    private static FileResource loadFileResource(){
        //TODO load file from spring context
        FileResource f = null;
        try {
            Resource resource = new ClassPathResource("fileResource.xml");
            f = loadXmlFile(resource.getInputStream(), FileResource.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return f;
    }

    /** load a specified xml file and convert to pojo
     * @param filePath xml file path
     * @param clazz class type
     * */
    private static <T> T loadXmlFile(String filePath, Class<T> clazz) throws IOException {
        if(filePath == null || clazz == null){
            return null;
        }
        ObjectMapper xmlMapper = new XmlMapper();
        T value;
        try {
            value = xmlMapper.readValue(new File(filePath), clazz);
        } catch (IOException e) {
            System.err.println("Exception occur when loadFile("+filePath+","+clazz.getName()+")");
            throw e;
        }
        return value;
    }

    /** load a specified xml input stream and convert to pojo
     * @param is xml file path
     * @param clazz class type
     * */
    private static <T> T loadXmlFile(InputStream is, Class<T> clazz) throws IOException {
        if(is == null || clazz == null){
            return null;
        }
        ObjectMapper xmlMapper = new XmlMapper();
        T value;
        try {
            value = xmlMapper.readValue(is, clazz);
        } catch (IOException e) {
            //System.err.println("Exception occur when loadFile("+filePath+","+clazz.getName()+")");
            e.printStackTrace();
            throw e;
        }
        return value;
    }


    /** traversal root directory, add file to file list*/
    private static void getAllFilesFromDirectory(File rootFile,List<File> fileList){
        if(rootFile == null || !rootFile.exists()){
            return;
        }
        if(!rootFile.isDirectory()){
            fileList.add(rootFile);
        }else{
            File[] files = rootFile.listFiles();
            if(files == null || files.length == 0){
                return;// empty directory
            }

            for(File i: files){
                getAllFilesFromDirectory(i,fileList);
            }
        }
    }

    /** convert file list to VideoDTO list*/
    private static void FileListToDto(List<File> fileList){
        ResourceDto vd;//resourceDto cache

        for (File i:fileList){
            String name = i.getName();//simple file name
            String suffix = name.substring(name.lastIndexOf(".") + 1);

            if(videoSuffixArray.contains(suffix)){//video resource
                vd = new ResourceDto(name,i.getPath(), UUID.randomUUID().toString(), suffix, ResourceType.video);
                videoDtoList.add(vd);//add file

            }else if(pdfSuffixArray.contains(suffix)){//pdf resource
                vd = new ResourceDto(name,i.getPath(), UUID.randomUUID().toString(), suffix, ResourceType.pdf);
                pdfDtoList.add(vd);//add file
            }
        }
    }
}
